package com.heima.wemedia.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.apis.article.IArticleClient;
import com.heima.apis.schedule.IScheduleClient;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.schedule.dto.Task;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.model.wemedia.vo.WmNewsVo;
import com.heima.utils.ProtostuffUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.AutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.thread.UserThreadLoacl;
import com.sun.org.apache.regexp.internal.RE;
import io.swagger.annotations.Authorization;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.UserTokenHandler;
import org.omg.PortableInterceptor.SUCCESSFUL;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl  extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private AutoScanService autoScanService;

    @Autowired
    private IScheduleClient scheduleClient;

    @Autowired
    private KafkaTemplate kafkaTemplate;
    
    @Autowired
    private WmUserMapper wmUserMapper;

    @Autowired
    private IArticleClient iArticleClient;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ResponseResult passOrFail(NewsAuthDto dto, short status) {
        if (dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        Integer id = dto.getId();
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章信息不存在");
        }

        wmNews.setStatus(status);
        wmNews.setReason(status == 9 ? "审核通过" : dto.getMsg());
        int update = wmNewsMapper.updateById(wmNews);
        if (update < 1){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"文章信息修改失败");
        }

        if (status == 9){
            ArticleDto articleDto = autoScanService.wmNews2ArticleDto(wmNews);
            ResponseResult responseResult = iArticleClient.saveArticle(articleDto);
            if (responseResult == null || responseResult.getCode() != 200){
                throw  new RuntimeException("文章保存失败");
            }

        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult findWmNewsVo(Integer id) {
        if (id == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());

        WmNewsVo wmNewsVo = new WmNewsVo();
        BeanUtils.copyProperties(wmNews,wmNewsVo);
        if (wmUser != null){
            wmNewsVo.setAuthorName(wmUser.getName());
        }


        return ResponseResult.okResult(wmNewsVo);
    }

    /**
     * 管理员端进行审核的审核列表查询
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findList(NewsAuthDto dto) {
        if (dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        dto.checkParam();
        dto.setPage((dto.getPage() - 1) * dto.getSize());
        List<WmNewsVo> wmNewsVoList = wmNewsMapper.findListAndPage(dto);
        Integer count = wmNewsMapper.findCount(dto);

        ResponseResult responseResult = new PageResponseResult(dto.getPage(),dto.getSize(),count);
        responseResult.setData(wmNewsVoList);

        return responseResult;
    }

    @Override
    public ResponseResult downOrUp(WmNewsDto wmNewsDto) {
        if (wmNewsDto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        Integer newsId = wmNewsDto.getId();
        WmNews wmNews = wmNewsMapper.selectById(newsId);
        if (wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"新闻不存在");
        }

        Short status = wmNews.getStatus();
        if (9 != status){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"新闻未发布");
        }

        wmNews.setEnable(wmNewsDto.getEnable());
        int updateById = wmNewsMapper.updateById(wmNews);
        if (updateById < 1){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"修改文章上下驾失败");
        }


        Map<String,Object> params = new HashMap<>();
        params.put("articleId",wmNews.getArticleId());
        params.put("enable",wmNews.getEnable());
        kafkaTemplate.send("downOrUp",JSON.toJSONString(params));

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 发布文章
     * @param dto
     * @return
     */
    @Override
    public ResponseResult submit(WmNewsDto dto) {
        //===========================参数非空判断===============================
        if (dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //==================必插之====================插入新闻类开始========================
        //构建新闻类，保存到新闻表
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(dto,wmNews);
        //做个方法，返回类型和封面，传入dto.getType(),Iamges,content
        Map<String,Object> typeAndIamges = getNewsTypeAndImages(dto.getType(),dto.getImages(),dto.getContent());
        Short type = (Short) typeAndIamges.get("type");
        List<String> coverImages = (List<String>) typeAndIamges.get("coverImages");
        List<String> contentImages = (List<String>) typeAndIamges.get("contentImages");
        String images = StringUtils.join(coverImages, ",");
        wmNews.setType(type);
        wmNews.setImages(images);
        wmNews.setUserId(UserThreadLoacl.get().getId());
        wmNews.setCreatedTime(new Date());
        int WmNewsinsert = wmNewsMapper.insert(wmNews);
        if (WmNewsinsert < 1){
            throw new RuntimeException("新闻插入失败");
        }
        //==================必插之====================插入新闻类结束========================

        //========================判断是不是草稿=========================
        //根据当前状态，也就是status
        if (wmNews.getStatus() == 0){
            //如果是草稿，就直接返回
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        //如果是提交，那就构建素材类和素材新闻关系类
        //==================================插入素材类开始 封面图和内容图都要插  关系表也在这个方法中==========================
        addMaterial(contentImages,0,wmNews.getId());
        addMaterial(coverImages,1,wmNews.getId());

        //审核   修改成延迟队列的版本
//        try {
//            autoScanService.autoScanWmNews(wmNews.getId());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        //在这里，先加入到延迟队列中，然后再有消费延迟队列的方法消费，拿到任务之后，再进行审核
        addTask(wmNews.getId(),wmNews.getPublishTime().getTime());
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    public void addTask(Integer newsId,Long executeTime){
        log.info("添加任务到延迟队列中---begin");
        Task task = new Task();
        task.setExecuteTime(executeTime);
        WmNews wmNews = new WmNews();
        wmNews.setId(newsId);
        task.setParameters(ProtostuffUtil.serialize(wmNews));
        scheduleClient.addTask(task);

        log.info("添加任务到延迟队列中---end");

    }


    //添加素材和素材新闻联系表
    private void addMaterial(List<String> images, int type, Integer newsId) {
        if (images == null){
         return;
        }
        for (String url : images) {
            //素材类
            WmMaterial wmMaterial = new WmMaterial();
            wmMaterial.setUserId(UserThreadLoacl.get().getId());
            wmMaterial.setType((short)0);
            wmMaterial.setCreatedTime(new Date());
            wmMaterial.setUrl(url);
            wmMaterial.setIsCollection((short)0);
            int wmMaterialInsert = wmMaterialMapper.insert(wmMaterial);
            if (wmMaterialInsert < 1){
                log.error("素材表插入失败");
                throw new RuntimeException("服务器繁忙");
            }
            //素材和新闻联系类
            WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
            wmNewsMaterial.setNewsId(newsId);
            wmNewsMaterial.setMaterialId(wmMaterial.getId());
            wmNewsMaterial.setType((short)type);
            wmNewsMaterial.setOrd((short)0);
            int wmNewsMaterialInsert = wmNewsMaterialMapper.insert(wmNewsMaterial);
            if (wmNewsMaterialInsert < 1){
                log.error("素材新闻中间表，插入失败");
                throw new RuntimeException("服务器繁忙");
            }
        }

    }

    //根据封面类型，返回存入数据库中的封面图参数，内容图参数以及新闻类型
    private Map<String, Object> getNewsTypeAndImages(Short type, List<String> images, String content) {
        Map<String,Object> result = new HashMap<>();
        List<String> coverImagesResult = images;
        List<String> contentImagesResult = new ArrayList<>();
        Short typeResult = type;
        List<Map> contentAll = JSON.parseArray(content, Map.class);
        for (Map map : contentAll) {
            if ("image".equals(map.get("type"))){
                contentImagesResult.add((String) map.get("value"));
            }
        }

        if (type == -1){
            //如果是-1那就是自动类型，那就要根据内容返回对应的封面，内容，类型
            int size = contentImagesResult.size();
            if (size > 3){
                coverImagesResult = contentImagesResult.subList(0,3);
                typeResult = 3;
            }else if (size == 3){
                coverImagesResult = contentImagesResult;
                typeResult = 3;
            }else if (size == 2){
                coverImagesResult.add(contentImagesResult.get(0));
                coverImagesResult.add(contentImagesResult.get(1));
                typeResult = 3;
            }else if (size == 1){
                coverImagesResult.add(contentImagesResult.get(0));
                typeResult = 1;
            }else if (size == 0){
                typeResult = 1;
            }
        }
        result.put("type",typeResult);
        result.put("coverImages",coverImagesResult);
        result.put("contentImages",contentImagesResult);
        return result;
    }

    @Override
    public ResponseResult findAll(WmNewsPageReqDto dto) {
        if (dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        Short status = dto.getStatus();
        Integer channelId = dto.getChannelId();
        String keyword = dto.getKeyword();
        Date beginPubDate = dto.getBeginPubDate();
        Date endPubDate = dto.getEndPubDate();

        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(status != null,WmNews::getStatus,status);
        queryWrapper.eq(channelId != null,WmNews::getChannelId,channelId);
        queryWrapper.between(beginPubDate != null && endPubDate != null,
                WmNews::getPublishTime,beginPubDate,endPubDate);
        queryWrapper.like(!StringUtils.isEmpty(keyword),WmNews::getTitle,keyword);
        queryWrapper.eq(WmNews::getUserId, UserThreadLoacl.get().getId());


        Integer currentPage = dto.getPage();
        Integer size = dto.getSize();
        Page<WmNews>  page = new Page<>(currentPage,size);
        Page<WmNews> pageResult = wmNewsMapper.selectPage(page, queryWrapper);
        Long total = pageResult.getTotal();
        PageResponseResult pageResponseResult = new PageResponseResult(currentPage,size,total.intValue());
        pageResponseResult.setData(pageResult.getRecords());

        return pageResponseResult;
    }
}
